import requests
import json
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.hazmat.primitives import serialization
from urllib.parse import urlparse, quote, urlencode, urlunparse
import base64
import datetime
import random
import string
import time
import uuid

# 微信支付相关参数
appid = "wx499a94f9d35b7545"  # 微信支付分配的公众账号ID
mchid = "1680751724"  # 微信支付分配的商户号
serial_no = "2D7E875B491709DF339566875F784040A1E04622"  # 商户证书序列号
pay_key = "Kangjin1234567891478523697896541"  # 商户支付密钥 api_key(api_v3_key)
wx_notify_url = "https://127.0.0.1:8000/api/wx_notify"  # 微信支付异步通知回调地址
wx_pay_url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"  # 微信预支付接口地址


# 微信支付接口调用示例
# 1. 调用统一下单接口获取 prepay_id
# 2. 调用支付接口，调起微信支付界面
# 3. 支付成功后，微信服务器会回调到你的服务器，通知你支付结果
# 4. 服务器根据微信服务器返回的结果，处理订单状态
def build_authorization(path,
                        method,
                        data=None,
                        nonce_str=None):
    """
    生成token
    :param method: http请求的方法（get，post，put）
    :param path: 获取请求的绝对url，并去除域名部分得到参与签名的url。如果请求中有查询参数，url末尾应附加有'?'和对应的查询字符串
    :param data: 获取请求中的请求报文主体,
    :param nonce_str: 随机串
    :return:
    """
    with open("application/apps/cert/kg_apiclient_key.pem", "rb") as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None,  # 如果私钥有密码，提供相应的密码
        )

    timestamp = str(int(time.time()))
    nonce_str = nonce_str or ''.join(str(uuid.uuid4()).split('-')).upper()
    body = data if isinstance(data, str) else json.dumps(data) if data else ''
    sign_str = '%s\n%s\n%s\n%s\n%s\n' % (method, path, timestamp, nonce_str, body)
    signature = rsa_sign(private_key=private_key, sign_str=sign_str)
    authorization = 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%s",serial_no="%s"' % (mchid, nonce_str, signature, timeStamp, serial_no)
    return authorization
def rsa_sign(private_key, sign_str):
    """
    使用私钥对签名字符串进行签名
    :param private_key: 私钥
    :param sign_str: 签名字符串
    :return:
    """
    message = sign_str.encode('UTF-8')
    signature = private_key.sign(data=message, padding=padding.PKCS1v15(), algorithm=hashes.SHA256())
    return base64.b64encode(signature).decode('UTF-8').replace('\n', '')
def call_payment_api(price, description, openid):
    """
    调用微信支付接口，获取 prepay_id
    :param price: 支付金额
    :param description: 支付描述
    :param openid: 用户的 openid
    :return:
    """
    url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi"
    out_trade_no = ''.join(random.sample(string.ascii_letters + string.digits, 8))
    data = {
        "appid": appid,
        "mchid": mchid,
        "description": description,
        "notify_url": wx_notify_url,
        "out_trade_no": out_trade_no,  # 生成你自己的唯一订单号
        "amount": {"total": price},
        "payer": {"openid": openid}
    }
    body = json.dumps(data)
    authorization = build_authorization('/v3/pay/transactions/jsapi', "POST", body)
    headers = {
        "Content-Type": "application/json",
        "Authorization": authorization
    }
    response = requests.post(url, headers=headers, data=body)
    print(f"Response: {response.text}")
    return response.json()

def handle_payment_result(result):
    if "prepay_id" in result:
        # 支付请求成功，获取到 prepay_id
        prepay_id = result["prepay_id"]
        # 这里可以将 prepay_id 返回给前端，以便前端调起支付界面
        return prepay_id
    else:
        # 支付请求失败，处理错误信息
        print(f"Payment failed: {result['message']}")
        return None


if __name__ == "__main__":
    # 测试数据
    price = 100  # 支付金额
    description = "Test payment"  # 支付描述
    openid = "oogzA68lRguok77ku-GCthpmqybM"  # 用户的 openid
    payment_result = call_payment_api(price, description, openid)
    prepay_id = handle_payment_result(payment_result)
    if prepay_id:
        print("Prepay ID:", prepay_id)